/****************************************************************
 ** Product  :   HP Subscriber Network Application Policy
 ** Module   :   gr-manager
 ** Date: Apr 10, 2015               
 ** Author: Chen Zhenhua
 ** (C) Copyright 2015, Hewlett-Packard Company, All Rights Reserved.
 ** This software is the proprietary information of HP, Inc.  
 ** Use is subject to license terms.
 *****************************************************************
 ** Description:   
 **    Update the session server global config.
 **    
 ****************************************************************/
package com.hp.snap.gr.action.impl;

import com.hp.snap.gr.exception.ActionException;
import com.hp.snap.gr.model.jaxb.ActionType;
import com.hp.snap.gr.model.jaxb.GeneralActionType;
import com.hp.snap.gr.model.jaxb.ParameterType;
import com.hp.snap.gr.utils.Constants;
import com.hp.snap.gr.utils.GRMConfigManager;
import com.hp.snap.gr.utils.SSConfigUtils;
import com.hp.snap.gr.utils.Utils;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * 
 * Update the session server global configuration to set the default business service status after session server started;
 * 
 * There are two parameter can be configured in the action: GLOBAL_KERNEL_CONFIG_NODE and BIZ_SERVICE_STATUS.
 * GLOBAL_KERNEL_CONFIG_NODE: The global KernelConfig node path in config server.
 * BIZ_SERVICE_STATUS: The status to be set; it has two optional values: Standby or Running.
 * 
 * <P>
 * Version: 3.3 <br>
 * Author: Chen Zhenhua 
 * Date: Apr 10, 2015
 * 
 * </P>
 * 
 **/
public class SetGlobalBizServiceFlagActionHandler extends AbstractActionHandler {

    public static final String SNAP_RTC_COMMON_KERNEL_CONFIG = "/SNAP/RTC/Common/KernelConfig";
    public static final String SNAP_UPM_COMMON_KERNEL_CONFIG = "/SNAP/UPM/Common/KernelConfig";
    public static final String ATTR_BIZ_SERVICE_STATUS = "bizServiceStatus";

    private static Logger logger = LoggerFactory.getLogger(SetGlobalBizServiceFlagActionHandler.class);

    /**
     * Current general action handler requires two parameter:
     * 1. BIZ_SERVICE_STATUS, which has two optional values:
     * Standby
     * Running
     * <p/>
     * 2. GLOBAL_KERNEL_CONFIG_NODE: the node of global kernel config path
     *
     * @param action            The action object/definition
     * @param actionPlanInputs  The global input parameters for all actions in this action plan
     * @param actionPlanOutputs The global output parameters for all actions in this action plan
     * @throws ActionException
     */
    @Override
    public void execute(ActionType action, Map<String, Object> actionPlanInputs,
                        Map<String, Object> actionPlanOutputs) throws ActionException {
        
        
        try {
            GeneralActionType actionType = (GeneralActionType) action;
            List<ParameterType> parameterTypes = actionType.getParameter();
            Map<String, String> parameterMap = Utils.contructParamMap(parameterTypes);

            // the new status flag
            String bizServiceStatus = parameterMap.get("BIZ_SERVICE_STATUS");
            
            if(bizServiceStatus.equalsIgnoreCase(Constants.KERNEL_CONFIG_RUNNING)){
                Constants.CONSOLE.info("All session servers are ready, the site can work now.");
                Constants.CONSOLE.info("The GR is updating kernel config, and set the GR status. ");
            }
                

            // the global KernelConfig node, you can choose to config a specific one, or update KernelConfig for both RTC and UPM
            String globalKernelConfigNode = parameterMap.get("GLOBAL_KERNEL_CONFIG_NODE");

            String ssConfigFile = GRMConfigManager.getGRGlobalConfigPath();

            SSConfigUtils.readSSConfig(ssConfigFile);

            boolean isNodeExist = false;
            boolean result = false;
            if (!StringUtils.isEmpty(globalKernelConfigNode)) {
                if (isNodeExist(globalKernelConfigNode)) {
                    isNodeExist = true;
                    result = updateBizServiceStatus(bizServiceStatus, globalKernelConfigNode);
                }
            } else {
                if (isNodeExist(SNAP_RTC_COMMON_KERNEL_CONFIG)) {
                    isNodeExist = true;
                    result = updateBizServiceStatus(bizServiceStatus, SNAP_RTC_COMMON_KERNEL_CONFIG);
                }

                if (isNodeExist(SNAP_UPM_COMMON_KERNEL_CONFIG)) {
                    isNodeExist = true;
                    result = (result || updateBizServiceStatus(bizServiceStatus, SNAP_UPM_COMMON_KERNEL_CONFIG));
                }
            }

            if (!isNodeExist) {
                throw new ActionException("The global KernelConfig node to be update is not exist!");
            }

            if (result) {
                SSConfigUtils.saveSSConfig(ssConfigFile);

                SSConfigUtils.importConfigServer(ssConfigFile);
            }

        } catch (ActionException e) {
            throw e;
        } catch (Exception e) {
            throw new ActionException(e.getMessage(), e);
        }

    }

    private boolean isNodeExist(String globalKernelConfigNode) {
        return GRMConfigManager.getGrGlobalConfig().containsKey("[" + globalKernelConfigNode + "]");
    }

    private boolean updateBizServiceStatus(String bizServiceStatus, String globalKernelConfigNode) {
        if (logger.isDebugEnabled()) {
            logger.debug("Start to update the KernelConfig: {}, to status: {}", globalKernelConfigNode, bizServiceStatus);
        }

        String oldValue = Utils.getConfigurationValue(globalKernelConfigNode, ATTR_BIZ_SERVICE_STATUS);

        if (!StringUtils.isEmpty(oldValue)) {
            if (!oldValue.equals(bizServiceStatus)) {
                SSConfigUtils.replaceConfig(globalKernelConfigNode, ATTR_BIZ_SERVICE_STATUS, oldValue, bizServiceStatus);
            } else {
                logger.debug("The business service flag in KernelConfig to be update is same!");
                return false;
            }
        } else {
            SSConfigUtils.addConfig(globalKernelConfigNode, ATTR_BIZ_SERVICE_STATUS, bizServiceStatus, false, -1);
        }
        return true;
    }


}
